package org.railage.client.gui.tabs;

import java.awt.Dialog.ModalityType;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.swing.ButtonGroup;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.JTable;
import javax.swing.JButton;
import javax.swing.SpinnerDateModel;
import javax.swing.table.DefaultTableModel;

import org.apache.log4j.Logger;
import org.railage.client.Client;
import org.railage.client.gui.dialogs.TicketBuyDialog;
import org.railage.client.gui.main.GUI;
import org.railage.common.dto.TripThroughTwoStationsDTO;

import javax.swing.JRadioButton;

public class TripSearchTab extends AbstractTab {

	private static final long serialVersionUID = 7869887107404755908L;

	private static final Logger log = Logger.getLogger(TripSearchTab.class);

	private static final String SELECT_STATION = "-- Select station --";

	private JComboBox<String> comboBoxStationA;
	private JComboBox<String> comboBoxStationB;

	private JSpinner departureTextField;
	private JSpinner arrivalTextField;
	private JSpinner durationTextField;

	private JRadioButton rdbtnAllTrips;
	private JRadioButton rdbtnTimePeriod;
	private JRadioButton rdbtnDuration;

	private JTable tripTable;

	private SimpleDateFormat dateTimeFormatter = new SimpleDateFormat(
			GUI.DATE_FORMAT + " " + GUI.TIME_FORMAT);
	private SimpleDateFormat timeFormatter = new SimpleDateFormat(
			GUI.TIME_FORMAT);

	private String[] stations = null;
	private String[] columnNames = new String[] { "Departure from A",
			"Arrival to B", "Trip ID", "Route name", "Time period" };

	public TripSearchTab() {
		setLayout(null);

		rdbtnAllTrips = new JRadioButton("All trips");
		rdbtnAllTrips.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				departureTextField.setEnabled(false);
				arrivalTextField.setEnabled(false);
				durationTextField.setEnabled(false);
			}
		});
		rdbtnAllTrips.setSelected(true);
		rdbtnAllTrips.setBounds(6, 16, 109, 23);
		add(rdbtnAllTrips);

		rdbtnTimePeriod = new JRadioButton("By time period");
		rdbtnTimePeriod.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				departureTextField.setEnabled(true);
				arrivalTextField.setEnabled(true);
				durationTextField.setEnabled(false);
			}
		});
		rdbtnTimePeriod.setBounds(6, 42, 109, 23);
		add(rdbtnTimePeriod);

		rdbtnDuration = new JRadioButton("By duration");
		rdbtnDuration.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				departureTextField.setEnabled(false);
				arrivalTextField.setEnabled(false);
				durationTextField.setEnabled(true);
			}
		});
		rdbtnDuration.setBounds(6, 69, 109, 23);
		add(rdbtnDuration);

		ButtonGroup buttonGroup = new ButtonGroup();
		buttonGroup.add(rdbtnAllTrips);
		buttonGroup.add(rdbtnTimePeriod);
		buttonGroup.add(rdbtnDuration);

		departureTextField = new JSpinner(new SpinnerDateModel());
		JSpinner.DateEditor departureTextFieldEditor = new JSpinner.DateEditor(
				departureTextField, GUI.DATE_FORMAT + " " + GUI.TIME_FORMAT);
		departureTextField.setEditor(departureTextFieldEditor);
		departureTextField.setEnabled(false);
		departureTextField.setToolTipText("departure date & time");
		departureTextField.setBounds(121, 41, 137, 20);
		add(departureTextField);

		arrivalTextField = new JSpinner(new SpinnerDateModel());
		JSpinner.DateEditor arrivalTextFieldEditor = new JSpinner.DateEditor(
				arrivalTextField, GUI.DATE_FORMAT + " " + GUI.TIME_FORMAT);
		arrivalTextField.setEditor(arrivalTextFieldEditor);
		arrivalTextField.setEnabled(false);
		arrivalTextField.setToolTipText("arrival date & time");
		arrivalTextField.setBounds(268, 41, 136, 20);
		add(arrivalTextField);

		durationTextField = new JSpinner(new SpinnerDateModel());
		JSpinner.DateEditor durationTextFieldEditor = new JSpinner.DateEditor(
				durationTextField, GUI.TIME_FORMAT);
		durationTextField.setEditor(durationTextFieldEditor);
		durationTextField.setEnabled(false);
		durationTextField.setBounds(121, 70, 67, 20);
		add(durationTextField);

		JLabel lblStationA = new JLabel("Station A");
		lblStationA.setBounds(437, 14, 63, 14);
		add(lblStationA);

		comboBoxStationA = new JComboBox<String>();
		comboBoxStationA.setBounds(510, 11, 200, 20);
		add(comboBoxStationA);

		JLabel lblStationB = new JLabel("Station B");
		lblStationB.setBounds(437, 42, 63, 14);
		add(lblStationB);

		comboBoxStationB = new JComboBox<String>();
		comboBoxStationB.setBounds(510, 39, 200, 20);
		add(comboBoxStationB);

		JButton btnSearch = new JButton("Search");
		btnSearch.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				if (rdbtnAllTrips.isSelected()) {
					fillTriptable((String) comboBoxStationA.getSelectedItem(),
							(String) comboBoxStationB.getSelectedItem(), null,
							null, null);
				} else if (rdbtnTimePeriod.isSelected()) {
					fillTriptable((String) comboBoxStationA.getSelectedItem(),
							(String) comboBoxStationB.getSelectedItem(),
							dateTimeFormatter.format(departureTextField
									.getValue()), dateTimeFormatter
									.format(arrivalTextField.getValue()), null);
				} else if (rdbtnDuration.isSelected()) {
					fillTriptable((String) comboBoxStationA.getSelectedItem(),
							(String) comboBoxStationB.getSelectedItem(), null,
							null,
							timeFormatter.format(durationTextField.getValue()));
				}
			}
		});
		btnSearch.setBounds(621, 72, 89, 23);
		add(btnSearch);

		JScrollPane scrollPane = new JScrollPane();
		scrollPane.setBounds(0, 106, 720, 284);
		add(scrollPane);

		tripTable = new JTable();
		tripTable.addMouseListener(new MouseAdapter() {
			public void mouseClicked(MouseEvent e) {
				if (e.getClickCount() == 2) {
					int row = tripTable.rowAtPoint(e.getPoint());
					int tripID = (Integer) tripTable.getValueAt(row, 2);
					TicketBuyDialog ticketDialog = new TicketBuyDialog(tripID);
					ticketDialog
							.setModalityType(ModalityType.APPLICATION_MODAL);
					ticketDialog.init();
				}
			}
		});
		scrollPane.setViewportView(tripTable);
	}

	public void init() {
		fillComboboxes();
		setTriptableModel(new Object[][] {});
	}

	private void fillComboboxes() {
		try {
			stations = (String[]) Client.getInstance().callMethod(
					"getStationNames", null);
			String[] items = new String[stations.length + 1];
			items[0] = SELECT_STATION;
			System.arraycopy(stations, 0, items, 1, stations.length);

			comboBoxStationA.setModel(new DefaultComboBoxModel<String>(items));
			comboBoxStationB.setModel(new DefaultComboBoxModel<String>(items));
		} catch (IOException e) {
			log.error(GUI.DISCON_UNEXP_LOG_MSG, e);
			JOptionPane.showMessageDialog(this, GUI.DISCON_UNEXP_GUI_MSG);
		}
	}

	private void fillTriptable(String stationA, String stationB,
			String startTime, String finishTime, String duration) {
		Object[][] data = new Object[][] {};
		if (!stationA.equals(SELECT_STATION)
				&& !stationB.equals(SELECT_STATION)) {
			TripThroughTwoStationsDTO[] trips = null;
			String[] request = null;
			if (startTime == null && finishTime == null && duration == null) {
				request = new String[] { stationA, stationB };
			} else if (startTime == null && finishTime == null) {
				request = new String[] { stationA, stationB, duration };
			} else if (duration == null) {
				request = new String[] { stationA, stationB, startTime,
						finishTime };
			}
			try {
				trips = (TripThroughTwoStationsDTO[]) Client.getInstance()
						.callMethod("getTripsThroughTwoStations", request);
				data = new Object[trips.length][];
				int i = 0;
				for (TripThroughTwoStationsDTO trip : trips) {
					Date departureFromA = new Date(trip.getDepartureFromA()
							.getTime());
					Date arrivalToB = new Date(trip.getArrivalToB().getTime());
					data[i] = new Object[] {
							dateTimeFormatter.format(departureFromA),
							dateTimeFormatter.format(arrivalToB),
							trip.getTrip(), trip.getRouteName(),
							trip.getDuration() };
					i++;
				}
			} catch (IOException e) {
				log.error(GUI.DISCON_UNEXP_LOG_MSG, e);
				JOptionPane.showMessageDialog(this, GUI.DISCON_UNEXP_GUI_MSG);
			}
		} else {
			String msg = "Some fields are not filled";
			log.warn(msg);
			JOptionPane.showMessageDialog(this, msg);
		}
		setTriptableModel(data);
	}

	private void setTriptableModel(Object[][] data) {
		tripTable.setModel(new DefaultTableModel(data, columnNames) {
			private static final long serialVersionUID = 6635154513743793121L;

			@Override
			public boolean isCellEditable(int row, int column) {
				return false;
			}
		});
		tripTable.getColumnModel().getColumn(0).setPreferredWidth(80);
		tripTable.getColumnModel().getColumn(1).setPreferredWidth(80);
		tripTable.getColumnModel().getColumn(2).setPreferredWidth(50);
		tripTable.getColumnModel().getColumn(3).setPreferredWidth(210);
		tripTable.getColumnModel().getColumn(4).setPreferredWidth(80);
	}
}
